package mt.filter;

import java.util.ArrayList;
import java.util.HashMap;

import mt.Order;
import mt.comm.ServerComm;
import mt.comm.ServerSideMessage;
import mt.comm.ServerSideMessage.Type;
import mt.dummy.ServerCommDummy;

/**
 * The filter is responsible for...
 * 
 * @author Filipe Pedras
 * @author Jorge Nogueira
 * @author Indira Sanches
 * @author Daniela Almeida
 *
 *
 */


public class AnalyticsFilter implements ServerComm {

	private ServerCommDummy decoratedServerComm;
	private HashMap<String, Integer> nicksBanned = new HashMap<String, Integer>();	
	private HashMap<String, Integer> lastTenSecMessage = new HashMap<String, Integer>();
	private long starttime;	
	private long newprinttime;
	private long last10secsAgo;
	private int buyOrder = 0;
	private int sellOrder = 0;
	private int totalBuyOrders = 0;
	private int totalSellOrders = 0;
	private int minPast = 0;
	

	public AnalyticsFilter(ServerCommDummy serverCommToDecorate) {
		decoratedServerComm = serverCommToDecorate;
	} 


	@Override
	public void start() {
		decoratedServerComm.start();
		starttime = System.currentTimeMillis();
		newprinttime=starttime+60000;
		last10secsAgo=System.currentTimeMillis();
	}

	/**
	 * The getNextMessage method verifies three situations and filter the messages.
	 * Disconnects the users whose submission orders are more than three orders in ten seconds 
	 * Calculates the average of purchases and sales per minute and print on the console.
	 * Prevents the entry on the banned list of clients.
	 * @return message
	 */
	@Override
	public ServerSideMessage getNextMessage() {
		ServerSideMessage message = decoratedServerComm.getNextMessage();

		if(!nicksBanned.containsKey(message.getSenderNickname())){
			if (lastTenSecMessage.containsKey(message.getSenderNickname()))
				lastTenSecMessage.put(message.getSenderNickname(), lastTenSecMessage.get(message.getSenderNickname()) + 1);
			else
				lastTenSecMessage.put(message.getSenderNickname(), 1);

			if(lastTenSecMessage.get(message.getSenderNickname())>=3){
				nicksBanned.put(message.getSenderNickname(), (int)System.currentTimeMillis());
				System.out.println("Banned: " + message.getSenderNickname());
				disconnectClient(message.getSenderNickname());
			}

			if(message.getType()==Type.NEW_ORDER){
				if(message.getOrder().isBuyOrder())
					buyOrder++;
				else if(message.getOrder().isSellOrder())
					sellOrder++;
			}
			if( System.currentTimeMillis()>=newprinttime){
				System.out.println("Buy count: "+buyOrder);
				System.out.println("Sell coun: "+sellOrder);
				minPast++;
				totalBuyOrders += buyOrder;
				totalSellOrders += sellOrder;
				System.out.println("Buy average: " + totalBuyOrders/minPast);
				System.out.println("Sell average: " + totalSellOrders/minPast);
				buyOrder = 0;
				sellOrder = 0;
				newprinttime=System.currentTimeMillis()+60000;
			}

			if ((int)System.currentTimeMillis()>=(int)last10secsAgo+10000){
				lastTenSecMessage.clear();
				last10secsAgo = System.currentTimeMillis();
			}
		} 

		else{
			ArrayList<String> temp = new ArrayList<String>(nicksBanned.keySet());
			for (String x : temp){
				if ((int)System.currentTimeMillis() - nicksBanned.get(x) >= 30000){
					nicksBanned.remove(x);
					return message;
				}
			}
			return null; 
		}

		return message;	

	}


	@Override
	public boolean hasNextMessage() {
		return decoratedServerComm.hasNextMessage();
	}

	@Override
	public void sendOrder(String receiversNickname, Order order) {
		decoratedServerComm.sendOrder(receiversNickname, order);
	}


	@Override
	public void sendError(String toNickname, String error) {
		decoratedServerComm.sendError(toNickname, error);
	}

	@Override
	public boolean clientIsConnected(String nickname) {
		return decoratedServerComm.clientIsConnected(nickname);
	}

	@Override 
	public void disconnectClient(String nickname) {
		decoratedServerComm.disconnectClient(nickname);
	}

	public int getTotalBuyOrders() {
		return totalBuyOrders;
	}

	public int getTotalSellOrders() {
		return totalSellOrders;
	}

	public int getSecondsPast() {
		return minPast;
	}

	public HashMap<String, Integer> getNicksBanned() {
		return nicksBanned;
	}

}
